package com.learn.hd.interview.lock;

import org.apache.curator.RetryPolicy;
import org.apache.curator.framework.CuratorFramework;
import org.apache.curator.framework.CuratorFrameworkFactory;
import org.apache.curator.framework.recipes.locks.InterProcessMutex;
import org.apache.curator.retry.ExponentialBackoffRetry;

import java.util.concurrent.CountDownLatch;

/**
 * @author zhanghaidong
 * @version v1.0
 * @description
 * @date 2019/7/19
 */
public class ZooKeeperLock {
    private static final String connetString = "116.196.113.135:2181";
    private static int sessionTimeOut = 2000;
    private static int count = 100;

    private static void process() {
        try {
            System.out.println(Thread.currentThread().getName() + ": acquire resource: " + count--);
        } catch (Exception e) {
            e.printStackTrace();
        }
    }
    public static void main(String[] args) throws Exception {
        //重试策略
        RetryPolicy retryPolicy = new ExponentialBackoffRetry(1000, 3);

        //创建工厂连接
        final CuratorFramework curatorFramework = CuratorFrameworkFactory.builder().connectString(connetString)
                .sessionTimeoutMs(sessionTimeOut).retryPolicy(retryPolicy).build();

        curatorFramework.start();

        //创建分布式可重入排他锁，监听客户端为curatorFramework，锁的根节点为/locks
        final InterProcessMutex mutex = new InterProcessMutex(curatorFramework, "/lock");
        final CountDownLatch countDownLatch = new CountDownLatch(1);

        for (int i = 0; i < 100; i++) {
            new Thread(() -> {
                try {
                    countDownLatch.await();
                    //加锁
                    mutex.acquire();
                    process();
                } catch (Exception e) {
                    e.printStackTrace();
                }finally {
                    try {
                        //释放锁
                        mutex.release();
                        System.out.println(Thread.currentThread().getName() + ": release lock");
                    } catch (Exception e) {
                        e.printStackTrace();
                    }
                }
            },"Thread" + i).start();
        }

        Thread.sleep(100);
        countDownLatch.countDown();

    }
}
